import threading
import socketserver


class Handler(socketserver.BaseRequestHandler):
    clients = {}
    def setup(self):
        super().setup()
        self.event = threading.Event()
        self.lock = threading.Lock()
        with self.lock:
             self.clients[self.client_address] = self.request

    def finish(self):
        super().finish()
        self.event.set()

    def handle(self):
        super().handle()

        while not self.event.is_set():
            try:
                data = self.request.recv(1024).decode()
            except Exception as e:
                data = 'quit'
            msg = data.strip()

            # 客户端退出命令
            if msg == 'quit' or msg == '': # 主动断开得到空字符串
                with self.lock:
                     self.clients.pop(self.client_address)
                     break
            msg = '{} {}'.format(self.client_address, data).encode()
            with self.lock:
                for f in self.clients.values():
                    f.send(msg)

def main():
    server = socketserver.ThreadingTCPServer(('127.0.0.1', 60000), Handler)
    threading.Thread(target=server.serve_forever, name='server', daemon=True).start()

    while True:
        cmd = input('>>')
        if cmd == 'quit':
            server.serve_close()
            threading.Event().wait(3)
            break

if __name__ == '__main__':
    main()


# 第一, 文件名不要取成python自己模块的名字, 会有冲突
# 第二, 端口好要在0-65535之间选择, 不能使用90000端口,这是系统限制
# 第三, 每个连接进来的话, 都有自己的一个clients属性, 无法实现群发, 因为里面只有自己一个clinet记载, 无法记载别的client
# 第四, 客户端发送断开请求的时候, 处理会有bug
